﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;

namespace Bonehead
{
    [TypeConverter(typeof(ExpandableObjectConverter))]
    public class ParsedMethod
    {
        private long mID;
        private string mName;
        private long mCallCount;
        private long mCycleCount;
        private long mMinCycleCount = long.MaxValue;
        private long mMaxCycleCount = long.MinValue;
        private long mTransitionCount;
        private long mExceptionCount;
        private Dictionary<ParsedMethod, CallerInfo> mCallers = new Dictionary<ParsedMethod, CallerInfo>();
        private Dictionary<ParsedMethod, CalleeInfo> mCallees = new Dictionary<ParsedMethod, CalleeInfo>();

        public ParsedMethod(long aID, string aName)
        {
            mID = aID;
            mName = aName;
        }

        public void AddCaller(ParsedMethod aMethod)
        {
            CallerInfo info;
            if (mCallers.TryGetValue(aMethod, out info))
            {
                info.AddCall();
            }
            else
            {
                info = new CallerInfo(aMethod);
                mCallers.Add(aMethod, info);
            }
        }

        public void AddCallee(ParsedMethod aMethod, long aCycles)
        {
            CalleeInfo info;
            if (mCallees.TryGetValue(aMethod, out info))
            {
                info.AddCall();
                info.AddCycles(aCycles);
            }
            else
            {
                info = new CalleeInfo(aMethod, aCycles);
                mCallees.Add(aMethod, info);
            }
        }

        public string Name
        {
            get { return mName; }
        }

        [Category("Performance"), DisplayName("Number of calls")]
        public long CallCount
        {
            get { return mCallCount; }
        }

        [Category("Performance"), DisplayName("Cycles inclusive")]
        public long CycleCount
        {
            get { return mCycleCount; }
        }

        [Category("Performance"), DisplayName("Minimum cycles inclusive")]
        public long MinCycleCount
        {
            get { return mMinCycleCount; }
        }

        [Category("Performance"), DisplayName("Maximum cycles inclusive")]
        public long MaxCycleCount
        {
            get { return mMaxCycleCount; }
        }

        [Category("Statistics")]
        public long Transitions
        {
            get { return mTransitionCount; }
        }

        [Category("Statistics"), DisplayName("Exceptions thrown")]
        public long ExceptionsThrown
        {
            get { return mExceptionCount; }
        }

        public void AddCall()
        {
            mCallCount++;
        }

        public void AddTransition()
        {
            mTransitionCount++;
        }

        public void AddException()
        {
            mExceptionCount++;
        }

        public void AddCycles(long aCycles)
        {
            mCycleCount += aCycles;
            mMinCycleCount = Math.Min(mMinCycleCount, aCycles);
            mMaxCycleCount = Math.Max(mMaxCycleCount, aCycles);
        }

        public override string ToString()
        {
            return Name;
        }

        [Browsable(false)]
        public IEnumerable<CalleeInfo> Callees
        {
            get { return mCallees.Values; }
        }

        [Browsable(false)]
        public IEnumerable<CallerInfo> Callers
        {
            get { return mCallers.Values; }
        }
    }
}
